/**
 * @description canvas里的图片对象
 * @property {Object} canvas canvas对象
 * @property {type} image 图片对象
 * @property {Sting} showMode 渲染的图片模式，默认canvasEdge：canvas的边缘
 * @property {Number} dWidth 要渲染的目标宽度
 * @property {Number} dHeight 要渲染的目标高度
 * @property {String} [editMode]  模式，比如移动模式move，消除模式elinimate，普通模式normal(普通模式不能移动)
 */
import { imgUploadVerify } from "@/utils/auth";
import {
  touchStartMove,
  changePosition,
  tempMove,
  calcDistance,
} from "./move.js";
let moveTimer = null,
  scaleTimer = null;

const touchMoveLazyDefault = 15;
let lazyTimerTime = 0,
  touchMoveLazy = 0; // touchMove事件的防抖节流时间
let scaleLazyTime = 40,
  scaleAfterIgnoreMoveTime = 50;
let moveStart = {};
let lineWidth = 5;
let brushMultip = 3;
let isAction = false;
let touchStatus = -1; // touchstart是1，touchmove是2，touchend是3
let actionTimer = null;
let initialDistance, currentDistance;
let initialTouchDistance;
let dpr = 1;
let tempCount = 0;
class MyCanvas {
  constructor({
    canvasId,
    canvas,
    canvasEl,
    dpr: _dpr,
    brushSize = lineWidth,
    editMode,
    board,
    width,
    cWidth,
    cHeight,
    isCanScale = false,
  }) {
    dpr = _dpr || 1;
    this.dpr = dpr;
    if (canvasEl) {
      this.init({ canvasEl });
    } else {
      this.canvas = canvas;
      this.ctx = canvas.getContext("2d");
    }

    this.editMode = editMode || "normal"; // matting抠图，eliminate消图

    this.image = null;
    this.localPath = "";
    this.sWidth = "";
    this.brushSize = brushSize;
    this.isScale = false;
    // this.ctx.lineWidth = lineWidth * brushMultip;
    if (board || canvasEl) {
      this.board = board
        ? board
        : {
            width: canvasEl.width,
            height: canvasEl.height,
          };
    }

    this.sHeight = "";
    this.isCanScale = isCanScale; // 能否缩放，能的话支持双指放大缩小
    this.showMode = "canvasEdge"; // canvasEdge/source,canvasEdge,按canvas的边缘显示,source:按原图大小显示
    this.dWidth = ""; // 图片的渲染宽度
    this.dHeight = ""; // 图片的渲染高度

    this.sx = 0; // 显示原图的x坐标
    this.sy = 0; // 显示原图的y坐标
    this.dx = 0; // 目标x轴
    this.dy = 0; //目标y轴
    this.scale = ""; // 图片缩放比例

    this.touchStartObj = {
      x: 0,
      y: 0,
    };
    if (this.editMode == "eliminate") {
      this.elimitInit();
    }
  }
  set brushSize(val) {
    this.ctx.lineWidth = val * brushMultip;
  }

  init({ canvasEl }) {
    let { width, height, node: canvas } = canvasEl;
    let ctx = canvas.getContext("2d");
    canvas.width = width * dpr;
    canvas.height = height * dpr;
    canvas.cWidth = width;
    canvas.cHeight = height;
    ctx.scale(dpr, dpr);
    this.canvas = canvas;
    this.ctx = ctx;
    // uni.createSelectorQuery().select("#frontCanvas").fields({ node: true, size: true }).exec(res => {
    //   let { width, height } = res[0];
    //   let canvas = res[0].node
    //   let ctx = canvas.getContext('2d');
    //   canvas.width = width * dpr;
    //   canvas.height = height * dpr;
    //   canvas.cWidth = width;
    //   canvas.cHeight = height;
    //   ctx.scale(dpr, dpr);
    //   // canvas.height = height;

    //   behindBg.value.width = width;
    //   behindBg.value.height = height;
    //   canvasImage = new MyCanvas({
    //     // canvasId: 'myCanvas',
    //     canvas,
    //     board: { width, height },
    //     name: '插入图片的canvas',
    //   });
    // });
  }

  elimitInit() {
    this.ctx.beginPath();
  }

  /**
   * @description 选择本地图片
   * @returns
   */
  async chooseImage(validObj) {
    let that = this;
    const url = await imgUploadVerify(validObj ? validObj : null);
    await this.getImgInfoByPath(url);
    return {
      url,
    };
    // return new Promise((resolve, reject) => {
    //   imgUploadVerify
    //   wx.chooseImage({
    //     count: 1,
    //     sizeType: ["original", "compressed"],
    //     sourceType: ["album"],
    //     success: async (res) => {
    //       await this.getImgInfoByPath(res.tempFilePaths[0]);
    //       resolve(res);
    //     },
    //   });
    // });
  }
  async saveHistory() {
    let obj = {
      canvas: this.canvas,
      x: this.sx,
      y: this.sy,
      width: this.dWidth, // sWidth,
      height: this.dHeight, // sHeight,
      destWidth: this.image.width,
      destHeight: this.image.height,
    };
    const res = await uni.canvasToTempFilePath(obj);
    updateHistoryRecord({
      userPath: bgImagePath.value,
      maskPath: res.tempFilePath,
    });
  }
  updateHistoryRecord({ userPath, maskPath, composePath, change }) {
    this.historyActive.value = active.value + 1;
    bgImgList.push(maskPath);
    let insertObj = {
      userPath,
      maskPath,
      composePath,
    };
    bgImgListRef.value[active.value] = insertObj;
  }
  /**
   *
   * @param {*} param
   * @param {String} param.imgPath 图片路径
   */
  loadNetImage({ imgPath }) {
    return this.getImgInfoByPath(imgPath);
  }
  /**
   * @description 根据图片路径得到图片信息，为之后渲染图片做准备
   * @param {*} path
   */
  async getImgInfoByPath(path) {
    return new Promise((resolve, reject) => {
      uni.getImageInfo({
        src: path,
        success: (imageInfo) => {
          this.image = imageInfo;

          let { width, height, path } = imageInfo;

          this.localPath = path;
          this.sWidth = width;
          this.sHeight = height;

          resolve(imageInfo);
        },
      });
    });
  }
  /**
   * @description 切换模式
   * @param {*} editMode
   */
  switchMode(editMode) {
    this.editMode = editMode;

    if (this.editMode == "eliminate") {
      this.ctx.fillStyle = "#fff";
      this.ctx.strokeStyle = "#fff";
      this.ctx.beginPath();

      this.ctx.lineWidth = 10;
    }
    if (this.editMode == "normal") {
      if (this.ctx.globalCompositeOperation != "source-over") {
        this.ctx.globalCompositeOperation = "source-over";
      }
    }
  }
  /**
   * @description 开始触发
   * @param {*} e
   */
  touchStart(e) {
    tempCount = 0;
    // 消除
    moveStart = e.touches[0];
    this.ctx.strokeStyle = "#fff";
    this.isScale = false;
    // ctx.lineCap = "round";
    // this.ctx.lineWidth = 10;

    this.touchStartObj.x = e.touches[0].x;
    this.touchStartObj.y = e.touches[0].y;
    if (e.touches.length === 2) {
      touchMoveLazy = touchMoveLazyDefault;
      const touch1 = { x: e.touches[0].clientX, y: e.touches[0].clientY };
      const touch2 = { x: e.touches[1].clientX, y: e.touches[1].clientY };
      initialDistance = Math.hypot(touch2.x - touch1.x, touch2.y - touch1.y);
    } else {
      touchMoveLazy = 0;
    }
    if (this.editMode == "eliminate") {
      this.eliminateTouchStart(e);
    } else {
      isAction = true;

      touchStartMove(e);
    }
  }
  touchMove(e) {
    tempCount = tempCount + 1;
    clearTimeout(actionTimer);
    actionTimer = setTimeout(() => this.touchMoveFn(e), 1);
  }
  touchMoveFn(e) {
    debugger;
    // console.log(
    //   "myCanvas~touchMoveFn~节流",
    //   "ctx的模式",
    //   this.ctx.globalCompositeOperation
    // );

    isAction = true;
    if (this.isCanScale && e.touches.length == 2) {
      // 缩放

      this.ctx.globalCompositeOperation = "source-over";

      if (e.touches.length === 2 && initialDistance) {
        const touch1 = { x: e.touches[0].clientX, y: e.touches[0].clientY };
        const touch2 = { x: e.touches[1].clientX, y: e.touches[1].clientY };
        // currentDistance = calcDistance(touch1, touch2);

        let thresholdForScale = 30;
        const currentTouchDistance = Math.hypot(
          touch2.x - touch1.x,
          touch2.y - touch1.y
        );

        const deltaDistance = currentTouchDistance - initialDistance;
        // console.log(
        //   "touchmove和上次之间的距离",
        //   "上次",
        //   initialDistance,
        //   "现在",
        //   currentTouchDistance,
        //   "差距",
        //   Math.abs(deltaDistance)
        // );
        if (Math.abs(deltaDistance) > thresholdForScale) {
          this.isScale = true;
          setTimeout(() => {
            this.twoFingerScale(e);
          }, scaleLazyTime);
        } else {
          this.oneFingerMove(e);
        }
        // 根据currentDistance和initialDistance的变化判断是否缩放
        return;
      }
      // this.touchMoveMove(e);
    } else {
    }
    if (this.editMode == "eliminate") {
      this.eliminateTouchMove(e);
    } else if (this.editMode == "remove") {
      if (this.isScale) {
        return;
      } else {
        this.touchMoveRemove(e);
      }
    } else if (this.editMode == "recover") {
      this.touchMoveRecover(e);
    } else {
      this.ctx.globalCompositeOperation = "source-over";
      this.touchMoveMove(e);
    }
  }
  touchEnd({ e, activePath }) {
    isAction = false;
    this.ctx.globalCompositeOperation = "source-over";
    if (this.editMode == "remove") {
      this.localPath = activePath;
      // this.image.src = activePath;
      // let image = this.canvas.createImage();
      // this.image.src = activePath;
      // this.image = image;
      // this.image.onload = () => {
      //   this.reloadImage();
      // };
    }
    setTimeout(() => {
      if (!isAction) {
        this.isScale = false;
      }
    }, scaleAfterIgnoreMoveTime);
  }

  /**
   * @description 抠图开始触发
   * @param {*} e
   */
  touchStartMove(e) {
    if (e.touches.length == 1) {
      // 移动
      moveStart = e.touches[0];
    } else {
      // 缩放
      let { x, y } = e.touches[0];
      let startDistance = calcDistance(e.touches[0], e.touches[1]);
    }
  }
  /**
   * @description 消除开始触发
   * @param {*} e
   */
  eliminateTouchStart(e) {
    this.ctx.strokeStyle = "#fff";
    // ctx.lineCap = "round";
    // this.ctx.lineWidth = 10;

    this.touchStartObj.x = e.touches[0].x;
    this.touchStartObj.y = e.touches[0].y;
  }
  touchMoveBrushRemove(e) {
    this.ctx.strokeStyle;
  }
  /**
   * @description 前端画笔消除
   */
  touchMoveRemoveByImageData(e) {
    let { x, y } = e.touches[0];

    // (x = x - 4), (y = y - 4);
    (x = x * 3), (y = y * 3);
    let imageData = this.ctx.getImageData(
      x,
      y,
      this.ctx.lineWidth * 6,
      this.ctx.lineWidth * 6
    );
    let data = imageData.data;
    for (let i = 0; i < data.length; i += 4) {
      // imageData.data[i] = 30;
      // imageData.data[i + 1] = 144;
      // imageData.data[i + 2] = 255;
      imageData.data[i + 3] = 0;
    }
    this.ctx.putImageData(imageData, x, y);
  }
  touchMoveRemove(e) {
    this.ctx.globalCompositeOperation = "destination-out";
    this.ctx.lineJoin = "round";
    this.ctx.lineCap = "round";
    // this.ctx.strokeStyle = "rgba(0,0,0,.5)";
    this.ctx.beginPath();

    let ctx = this.ctx;
    const x = e.touches[0].x,
      y = e.touches[0].y;

    this.ctx.moveTo(this.touchStartObj.x, this.touchStartObj.y);
    this.ctx.lineTo(x, y);
    this.ctx.stroke();
    this.touchStartObj = {
      x,
      y,
    };
  }
  touchMoveRecover(e) {
    // this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.width);
    this.ctx.drawImage(this.image, this.dx, this.dy, this.dWidth, this.dHeight);
  }

  /**
   * @description 在移动模式中移动/双指放大缩小
   * @param {*} e
   * @returns
   */
  touchMoveMove(e) {
    let { x, y } = e.touches[0];

    // 判断用户只是手指停留而不是想要移动/缩放
    if (x == moveStart.x && y == moveStart.y) {
      return;
    }
    if (!this.isCanMove) {
      return;
    }
    if (e.touches.length == 1) {
      this.oneFingerMove(e);
    } else {
      this.twoFingerScale(e);
    }
  }
  /**
   * @description 单个手指触发移动
   * @param {*} e
   * @returns
   */
  oneFingerMove(e) {
    clearTimeout(moveTimer);
    if (this.isScale) {
      return;
    }
    // moveTimer = setTimeout(() => {
    let { x, y } = changePosition(e.touches[0]);
    this.dragImage({ x, y });
    // }, lazyTimerTime);
  }
  /**
   * @description 两根手指触发缩放
   * @param {*} e
   */
  twoFingerScale(e) {
    moveStart = e.touches[0];
    this.isScale = true;
    clearTimeout(scaleTimer);

    let { scale } = tempMove({
      e,
      scale: this.scale,
    });
    if (scale == 1) {
      // 双指只是停留在屏幕，其实并没有动，这种就不进行缩放
      // console.log(
      //   "twoFingerScale~scale==1",
      //   "双指只是停留在屏幕,其实没有动,不进行缩放"
      // );
      return;
    }
    this.updateImage({ scale });
  }
  async getAuth() {
    // 获取已经获得的权限列表
    const res = await uni.getSetting();
    return new Promise((resolve, reject) => {
      // 已获得存储相册授权
      if (res.authSetting["scope.writePhotosAlbum"]) {
        // 直接下载图片文件到本地
        resolve();
      } else if (res.authSetting["scope.writePhotosAlbum"] === undefined) {
        // 未获得存储相册授权
        uni.authorize({
          scope: "scope.writePhotosAlbum",
          success: (res) => {
            resolve();
          },
        });
      } else {
        uni.openSetting();
      }
    });
  }
  async getCanvasPath() {
    let getCanvasPathObj = {
      canvas: this.canvas,
      x: 0,
      y: 0,
      width: this.canvas.width, // sWidth,
      height: this.canvas.height, // sHeight,
      destWidth: this.importWidth || this.image.width,
      destHeight: this.importHeight || this.image.height,
    };

    return uni.canvasToTempFilePath(getCanvasPathObj);
  }
  async getImagePath() {
    let getImagePathObj = {
      canvas: this.canvas,
      x: this.dx,
      y: this.dy,
      width: this.dWidth, // sWidth,
      height: this.dHeight, // sHeight,
      destWidth: this.importWidth || this.image.width,
      destHeight: this.importHeight || this.image.height,
    };

    return uni.canvasToTempFilePath(getImagePathObj);
  }
  /**
   * @description 获得canvas里的图片的路径，目前主要是抠图的时候需要上传原图用这个
   */
  async saveCanvas() {
    const res1 = await this.getCanvasPath();
    let res = await this.getAuth();
    await uni.saveImageToPhotosAlbum({ filePath: res1.tempFilePath });
    wx.showToast({
      title: "保存成功",
    });
  }
  /**
   * @description 保存canvas里的图片，而不保存整张画图，目前主要是抠图的时候需要上传原图用这个
   */
  async saveImage() {
    const res1 = await this.getImagePath();
    let res = await this.getAuth();
    await uni.saveImageToPhotosAlbum({ filePath: res1.tempFilePath });
    wx.showToast({
      title: "保存成功",
    });
  }

  eliminateTouchMove(e) {
    this.ctx.lineJoin = "round";
    this.ctx.lineCap = "round";
    this.ctx.beginPath();

    let ctx = this.ctx;
    const x = e.touches[0].x,
      y = e.touches[0].y;

    this.ctx.moveTo(this.touchStartObj.x, this.touchStartObj.y);
    this.ctx.lineTo(x, y);
    this.ctx.stroke();
    this.touchStartObj = {
      x,
      y,
    };
  }

  /**
   * @description 拖动图片
   * @param {Object} positionObj xy移动距离坐标对象
   * @param {Number} positionObj.moveDistanceX 移动的x坐标，toX-startX的值负数就是往左边挪动，正数就是往右边挪动
   * @param {Number} positionObj.y 移动的y坐标，toY-startY的值负数就是往上边挪动，正数就是往下边挪动
   */
  dragImage({ x: moveDistanceX, y: moveDistanceY }) {
    // let x = this.dx + moveDistanceX < 0 ? 0 : this.dx + moveDistanceX;
    // let y = this.dy + moveDistanceY < 0 ? 0 : this.dy + moveDistanceY;
    let x = this.dx + moveDistanceX;
    let y = this.dy + moveDistanceY;
    this.setAxis({
      x,
      y,
    });
    this.reloadImage();
  }
  /**
   * @description 缩放图片
   * @param {Number} scale 缩放比例
   */
  updateImage({ scale }) {
    scale = scale > 1 ? 1.01 : 0.99;
    this.dWidth = this.dWidth * scale;
    this.dHeight = this.dHeight * scale;
    this.scale = this.scale * scale;
    this.setAxis();

    this.reloadImage();
  }
  /**
   * @description 设置图片的目标大小,默认靠canvas宽高和image宽高来确定要显示的宽高
   */
  setSize({ width, height } = {}) {
    let x,
      y = 0;
    let cWidth;

    if (width && height) {
      this.dWidth = width;
      this.dHeight = this.dHeight;
    } else if (this.showMode == "canvasEdge") {
      // 容器有多大就显示到容器边缘
      this.setDSizeByWrap();
    } else if (this.showMode == "source") {
      // 图片本身有多大显示多大
      this.dWidth = this.sWidth;
      this.dHeight = this.sHeight;
      x = (this.cWidth - this.dWidth) / 2;
      y = (this.cHeight - this.dHeight) / 2;
    }

    this.setAxis({ x, y });
  }
  /**
   *
   * @param {*} Wrap 设置目标大小
   */
  setDSizeByWrap() {
    let widthScale = this.image.width / this.board.width;
    let heightScale = this.image.height / this.board.height;
    let scale = 1;
    if (widthScale > 1 || heightScale > 1) {
      scale = widthScale > heightScale ? widthScale : heightScale;
    }
    this.dWidth = this.image.width / scale;
    this.dHeight = this.image.height / scale;
    this.scale = scale;
    this.setAxis();
  }

  /**
   * @description 设置坐标
   */
  setAxis(obj = {}) {
    let { x, y } = obj;
    this.dx = typeof x == "number" ? x : (this.board.width - this.dWidth) / 2;
    this.dy = typeof y == "number" ? y : (this.board.height - this.dHeight) / 2;
  }
  /**
   *
   *
   * @description 绘制图片
   */
  drawMyImage({ sX, sY, width, height } = {}) {
    this.setSize();

    this.setAxis();
    let image = this.canvas.createImage();
    image.src = this.localPath;
    image.onload = (res) => {
      this.image = image;
      // 绘制图像到canvas
      this.reloadImage();
    };
  }
  /**
   * @description 重新恢复图片原始状态
   */
  resetImage() {
    this.dx = 0;
    this.dy = 0;
    this.scale = 1;
    this.image.src = this.sourcePath;
    this.image.onload = (res) => {
      this.reloadImage();
    };
  }
  reloadImage() {
    this.ctx.globalCompositeOperation = "source-over";
    // 绘制图像到canvas
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    console.log("reloadImage", this.dx, this.dy, this.dWidth, this.dHeight);
    this.ctx.drawImage(this.image, this.dx, this.dy, this.dWidth, this.dHeight);
  }
}
export default MyCanvas;
